﻿using System.Collections.Generic;
using CI;
using CI.Interfaces;
using CI.Mesopotamia;
using CI.Organism;
using NUnit.Framework;
using Rhino.Mocks;

namespace Mesopotamia.UnitTests
{

    [TestFixture]
    public class EvolvingFitnessFunctionTest
    {
        private MockEvolvingFitnessFunction _evolvingFitnessFunction;
        private IOrganism _organism;
        private IHostingEnvironment _hostingEnvironment;
        private MockRepository _mockRepository;
        private IOrganismCollection _organismCollection;
        private System.Guid guid = System.Guid.NewGuid();

        [SetUp]
        public void Setup()
        {
            _evolvingFitnessFunction = new MockEvolvingFitnessFunction();
            _mockRepository = new MockRepository();
            _hostingEnvironment = _mockRepository.DynamicMock<IHostingEnvironment>();
            _organism = MockRepository.GenerateMock<IOrganism>();
            _organism.Stub(x => x.Guid).Return(guid);

            _organismCollection = _mockRepository.DynamicMock<IOrganismCollection>();
            _organismCollection.Alive = new SynchronizedCollection<IOrganism>();
            _organismCollection.Alive.Add(_organism);
            _organismCollection.Stub(x => x.DirtyLocations).Return(new List<IOrganism>());
        }

        [Test]
        public void UpdateOrganisms_IncrementsOneLevel_True()
        {
            _evolvingFitnessFunction.OrganismsFitnessLevel.Add(_organism, 0);
            _evolvingFitnessFunction.UpdateOrganisms(_organismCollection);
            Assert.AreEqual(1, _evolvingFitnessFunction.OrganismsFitnessLevel[_organism]);
        }

        [Test]
        public void UpdateOrganisms_IncrementsAllTheWay_True()
        {
            _evolvingFitnessFunction.OrganismsFitnessLevel.Add(_organism, 0);
            for (int i = 0; i < _evolvingFitnessFunction.HighestAvailableFitnessLevel() + 1; i++)
            {
                _evolvingFitnessFunction.UpdateOrganisms(_organismCollection);
            }

            Assert.AreEqual(_evolvingFitnessFunction.HighestAvailableFitnessLevel(), _evolvingFitnessFunction.OrganismsFitnessLevel[_organism]);
        }
    }

    public class MockEvolvingFitnessFunction : EvolvingFitnessFunction
    {

        public new Dictionary<IOrganism, int> OrganismsFitnessLevel
        {
            get
            {
                return base.OrganismsFitnessLevel;
            }
        }

        public new List<IFitnessLevelEvaluator> FitnessLevelEvaluators
        {
            get
            {
                return base.FitnessLevelEvaluators;
            }
        }

        public MockEvolvingFitnessFunction()
        {
            FitnessLevelEvaluators.Add(new TestFitnessLevelEvaluator1());
            FitnessLevelEvaluators.Add(new TestFitnessLevelEvaluator2());
            FitnessLevelEvaluators.Add(new TestFitnessLevelEvaluator3());
        }

        protected override void UpdateNewAndRemovedOrganisms(IOrganismCollection organisms)
        {
        }

        private class TestFitnessLevelEvaluator1 : IFitnessLevelEvaluator
        {
            #region IFitnessLevelEvaluator Members

            public void UpdateStrength(IOrganism organism)
            {
                return;
            }

            public bool UpgradeToNextLevel(IOrganism organism)
            {
                return true;
            }

            public void RemoveOrganism(IOrganism organism)
            {
                return;
            }

            public string ToString(IOrganism organism)
            {
                return "mock fitness eval";
            }

            #endregion
        }

        private class TestFitnessLevelEvaluator2 : TestFitnessLevelEvaluator1 { }
        private class TestFitnessLevelEvaluator3 : TestFitnessLevelEvaluator2 { }
    }
}
